package com.moss.cloud.base.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moss.cloud.base.api.model.from.BaseFrom;
import com.moss.cloud.base.api.model.from.SysDictFrom;
import com.moss.cloud.base.api.model.param.DictParam;
import com.moss.cloud.base.biz.mapper.SysDictMapper;
import com.moss.cloud.base.biz.model.SysDict;
import com.moss.cloud.base.biz.service.ISysDictService;
import com.moss.cloud.common.base.utils.PageUtil;
import com.moss.cloud.common.core.enums.DictCacheEnum;
import com.moss.cloud.common.core.exception.SystemErrorType;
import com.moss.cloud.common.core.model.vo.DictTreeVO;
import com.moss.cloud.common.core.utils.BooleanHandel;
import com.moss.cloud.common.core.utils.TreeUtil;
import com.moss.cloud.common.security.component.RedisTemplateOps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 字典管理业务实现
 *
 * @author 瑾年
 * @date 2023年11月21日
 */
@Slf4j
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements ISysDictService {
    private final RedisTemplateOps redisTemplateOps;

    public SysDictServiceImpl(RedisTemplateOps redisTemplateOps) {
        this.redisTemplateOps = redisTemplateOps;
    }

    /**
     * 字典树形结构数据查询
     *
     * @param dictParam
     * @return
     */
    @Override
    public IPage<DictTreeVO> dictTreeList(DictParam dictParam) {
        Page<SysDict> page = PageUtil.createPage(dictParam.getCurrent(), Long.MAX_VALUE);
        IPage<SysDict> sysDictIPage = this.page(page, new QueryWrapper<SysDict>().lambda()
                .eq(StringUtils.isNotBlank(dictParam.getDictGroup()), SysDict::getDictGroup, dictParam.getDictGroup())
                .like(StringUtils.isNotBlank(dictParam.getDictName()), SysDict::getDictName, dictParam.getDictName()));
        IPage<DictTreeVO> treeVOIPage = new Page<>();
        List<DictTreeVO> dictTreeVOList = CollectionUtils.isNotEmpty(sysDictIPage.getRecords()) ? sysDictIPage.getRecords()
                .stream().map(item -> {
                    DictTreeVO dictTreeVO = new DictTreeVO();
                    BeanUtils.copyProperties(item, dictTreeVO);
                    return dictTreeVO;
                }).collect(Collectors.toList()) : Collections.emptyList();
        List<DictTreeVO> tree = CollectionUtils.isNotEmpty(dictTreeVOList) ? TreeUtil.toTree(dictTreeVOList, 0L,
                DictTreeVO::getId, DictTreeVO::getParentId, DictTreeVO::setChildren)
                : Collections.emptyList();
        BeanUtils.copyProperties(sysDictIPage, treeVOIPage);
        treeVOIPage.setRecords(tree);
        return treeVOIPage;
    }

    /**
     * 新增字典
     *
     * @param sysDictFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveDict(SysDictFrom sysDictFrom) {
        SysDict sysDict = new SysDict();
        BeanUtils.copyProperties(sysDictFrom, sysDict);
        Boolean saveFlag = this.save(sysDict);
        BooleanHandel.isTrue(saveFlag).trueHandle(() ->
                redisTemplateOps.set(DictCacheEnum.DICT_CACHE.getKey() + sysDictFrom.getDictGroup() + ":" + sysDictFrom.getDictKey(), sysDict));
        return saveFlag;
    }

    /**
     * 编辑字典
     *
     * @param sysDictFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDict(SysDictFrom sysDictFrom) {
        BooleanHandel.trueThrow(Objects.isNull(sysDictFrom.getId())).throwMessage(SystemErrorType.PRIMARY_KEY);
        this.checkDict(sysDictFrom.getId());
        SysDict sysDict = new SysDict();
        BeanUtils.copyProperties(sysDictFrom, sysDict);
        Boolean updateFlag = this.updateById(sysDict);
        BooleanHandel.isTrue(updateFlag).trueHandle(() -> {
            redisTemplateOps.del(DictCacheEnum.DICT_CACHE.getKey() + sysDictFrom.getDictGroup() + ":" + sysDictFrom.getDictKey());
            redisTemplateOps.set(DictCacheEnum.DICT_CACHE.getKey() + sysDictFrom.getDictGroup() + ":" + sysDictFrom.getDictKey(), sysDict);
        });
        return updateFlag;
    }

    private SysDict checkDict(Long id) {
        SysDict sysDict = this.getById(id);
        BooleanHandel.trueThrow(Objects.isNull(sysDict)).throwMessage(SystemErrorType.DATE_EMPTY);
        return sysDict;
    }

    /**
     * 删除字典-物理删除
     *
     * @param baseFrom
     * @return
     */
    @Override
    public Boolean removeDict(BaseFrom baseFrom) {
        SysDict sysDict = this.checkDict(baseFrom.getId());
        long count = this.count(new QueryWrapper<SysDict>().lambda().eq(SysDict::getParentId, sysDict.getId()));
        BooleanHandel.trueThrow(count > 0).throwMessage(SystemErrorType.CHILDREN_NOT_EMPTY);
        Boolean delFlag = this.removeById(baseFrom.getId());
        BooleanHandel.isTrue(delFlag).trueHandle(() ->
                redisTemplateOps.del(DictCacheEnum.DICT_CACHE.getKey() + sysDict.getDictGroup() + ":" + sysDict.getDictKey()));
        return delFlag;
    }

    /**
     * 加载字典数据
     *
     * @return
     */
    @Override
    public Boolean overload() {
        List<SysDict> sysDicts = this.list(new QueryWrapper<>());
        BooleanHandel.isTrue(CollectionUtils.isNotEmpty(sysDicts)).trueHandle(() -> sysDicts.forEach(item ->
                redisTemplateOps.set(DictCacheEnum.DICT_CACHE.getKey() + item.getDictGroup() + ":" + item.getDictKey(), item)));
        return Boolean.TRUE;
    }


    /**
     * 查询分组下的字典数据
     *
     * @param dictParam
     * @return
     */
    @Override
    public List<SysDict> dictGroup(DictParam dictParam) {
        BooleanHandel.trueThrow(StringUtils.isBlank(dictParam.getDictGroup())).throwMessage(SystemErrorType.DICT_GROUP_EMPTY);
        List<String> keys = redisTemplateOps.keys(DictCacheEnum.DICT_CACHE.getKey() + dictParam.getDictGroup() + ":*");
        List<SysDict> sysDicts = new ArrayList<>(CollectionUtils.isNotEmpty(keys) ? keys.stream().map(item ->
                (SysDict) redisTemplateOps.get(item))
                .collect(Collectors.toList()) : Collections.emptyList());
        sysDicts.removeIf(x -> x.getParentId().equals(0L));
        return sysDicts;
    }

    /**
     * 查询字典KEY的数据
     *
     * @param dictParam
     * @return
     */
    @Override
    public SysDict dictKey(DictParam dictParam) {
        BooleanHandel.trueThrow(StringUtils.isBlank(dictParam.getDictGroup())).throwMessage(SystemErrorType.DICT_GROUP_EMPTY);
        BooleanHandel.trueThrow(StringUtils.isBlank(dictParam.getDictGroup())).throwMessage(SystemErrorType.DICT_KEY_EMPTY);
        boolean hasKey = redisTemplateOps.hasKey(DictCacheEnum.DICT_CACHE.getKey() + dictParam.getDictGroup() + ":" + dictParam.getDictKey());
        return hasKey ? (SysDict) redisTemplateOps.get(DictCacheEnum.DICT_CACHE.getKey() + dictParam.getDictGroup() + ":" + dictParam.getDictKey())
                : new SysDict();
    }


}
